import axios from 'axios'
import { Loading, Message } from 'element-ui'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { blobValidate } from "@/utils/ruoyi";

// import XLSX from "xlsx";
import XLSX from "xlsx-js-style";
import { parseTime } from "@/utils/ruoyi";

const baseURL = process.env.VUE_APP_BASE_API
let downloadLoadingInstance;

export default {
  name(name, isDelete = true, showRealName = false) {
    var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete + "&showRealName=" + showRealName
    axios({
      method: 'get',
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
    }).then(async (res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data])
        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
      } else {
        await this.printErrMsg(res.data);
      }
    })
  },
  resource(resource) {
    var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
    axios({
      method: 'get',
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
    }).then(async (res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data])
        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
      } else {
        await this.printErrMsg(res.data);
      }
    })
  },
  zip(url, name) {
    var url = baseURL + url
    downloadLoadingInstance = Loading.service({ text: "正在下载数据，请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
    axios({
      method: 'get',
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
    }).then(async (res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data], { type: 'application/zip' })
        this.saveAs(blob, name)
      } else {
        await this.printErrMsg(res.data);
      }
      downloadLoadingInstance.close();
    }).catch((r) => {
      console.error(r)
      Message.error('下载文件出现错误，请联系管理员！')
      downloadLoadingInstance.close();
    })
  },
  // 下载本地文件
  downloadFrontFile(path, name) {
    axios({
      method: 'get',
      url: path,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
    }).then(async (res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data], { type: 'application/zip' })
        this.saveAs(blob, name);
      } else {
        await this.printErrMsg(res.data);
      }
    })
  },
  saveAs(text, name, opts) {
    saveAs(text, name, opts);
  },
  async printErrMsg(data) {
    const resText = await data.text();
    const rspObj = JSON.parse(resText);
    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
    Message.error(errMsg);
  },

  /**
   * 导出页面静态表格
   * @param selector 表格选择器
   * @param fileName 导出文件名
   * @param valueAsString 值是否作为数字格式展示
   * @param config 导出项配置
   */
  exportTable(selector, fileName, valueAsString = true, config = {}) {
    let tableDom = document.querySelector(selector);
    let wb = XLSX.utils.table_to_book(tableDom, valueAsString ? { raw: true } : {});
    let ws = wb.Sheets.Sheet1;
    // 根据配置项进行相关处理
    const { border } = config;
    if (border) {
      this.addBorder(ws);
    }
    let wbout = XLSX.write(wb, {
      bookType: "xlsx",
      bookSST: true,
      type: "array"
    });
    try {
      saveAs(
        new Blob([wbout], { type: "application/octet-stream" }),
        (fileName || "数据导出-" + parseTime(new Date(), "{y}{m}{d}_{h}{i}{s}")) + ".xlsx"
      );
    } catch (e) {
    }
    return wbout;
  },
  /**
   * getRangeFromCells 获取真实的
   * @param cells ['A1', 'B1', 'G1', 'B2', 'C2', 'G2', 'F10']这样的数组
   */
  getRangeFromCells(cells) {
    let minCol = 0, maxCol = 0;
    let minRow = 0, maxRow = 0;
    cells.forEach(address => {
      // 使用 SheetJS 的 decode_cell 解析单元格地址
      const { c: col, r: row } = XLSX.utils.decode_cell(address);
      // 更新最小/最大行列
      if (col < minCol) minCol = col;
      if (col > maxCol) maxCol = col;
      if (row < minRow) minRow = row;
      if (row > maxRow) maxRow = row;
    });
    // 生成范围对象
    const range = {
      s: { r: minRow, c: minCol }, // 起始位置
      e: { r: maxRow, c: maxCol },  // 结束位置
    };
    return range;
  },
  /**
   * addBorder 导出内容增加边框
   * @param ws 具体sheet
   */
  addBorder(ws) {
    // 定义好边框样式
    const border = {
      top: { style: "thin" },
      bottom: { style: "thin" },
      left: { style: "thin" },
      right: { style: "thin" }
    }
    // 获取表格的有效范围
    // cellValueList: 是有值的单元格key值，这样为了计算真正的单元格范围
    const cellValueList = [];
    Object.entries(ws).forEach(([key, val]) => {
      if (val.v || val.v === 0) {
        cellValueList.push(key);
      }
    });
    // const range = XLSX.utils.decode_range(ws['!ref']);  这个范围大，所以不采用
    const range = this.getRangeFromCells(cellValueList);
    // 遍历表格
    const minCol = range.s.c;
    const minRow = range.s.r;
    const maxCol = range.e.c;
    const maxRow = range.e.r;
    for (let row = minRow; row <= maxRow; row++) {
      for (let col = minCol; col <= maxCol; col++) {
        // 通过行列转成excle的单元格索引
        const cell = XLSX.utils.encode_cell({ r: row, c: col });
        // 查找一下单元格是否已经存在，不存在：创建一个单元格并设置边框，存在：直接修改样式
        if (cellValueList.indexOf(cell) < 0) {
          ws[cell] = { t: '', v: '', s: { border } }
        } else {
          ws[cell].s = { border }
        }
      }
    }
  },

  /**
   * 生成uuid
   * @param len 长度
   * @param radix 位数
   * @return {string} 最终的uuid
   */
  guid(len, radix) {
    const chars =
      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
    let uuid = [],
      i;
    radix = radix || chars.length;

    if (len) {
      // Compact form
      for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
    } else {
      // rfc4122, version 4 form
      var r;

      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-";
      uuid[14] = "4";

      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | (Math.random() * 16);
          uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
        }
      }
    }

    return uuid.join("");
  }
}

